/*********************************************************************

	SCUMiX(R) SWAT JavaScript Toolkit
	ext.CTimer.js

	author: scumyang
	create: 2011-08-23
	desc. : 定时器
	update: 

*********************************************************************/

/*

** 用例 **
queue = new $.ext.algorithm.queue();
for( var i=0; i<5; i++ )
	queue.put( {id:i,text:''} );

timer = new $.ext.CTimer( foo, {interval:300, maxConcurrence:4, param:queue} );
timer.start( queue.size());

** 扩展参数 **
maxConcurrence: 最大并发执行数
interval: 定时器执行时间间隔(毫秒)
maxRunCount: 最大运行次数上限

*/

/**
 * Swat Ext: CTimer
 */
if( swat && swat.version >= 3.0 )
{
	/**
	 * 构造
	 * @param __callback: 回调函数
	 * @param P: (可选)扩展参数
	 */
	swat.ext.CTimer = function( __callback, P )
	{
		if( typeof __callback != 'function' ) return false;

		this.className = 'ext.CTimer';

		this.m_runCount = 0;	// 当前运行次数
		this.m_runCon = 0;		// 当前并发数
		this.m_hTimer = 0;		// 定时器句柄

		this.m_timerProc = __callback;	// 回调函数

		// 初始化扩展参数
		this.m_maxCon = P ? P.maxConcurrence || 0 : 0;
		this.m_interval = P ? P.interval || 500 : 500;
		this.m_maxRunCount = P ? P.maxRunCount || -1 : -1;
		this.m_param = P ? P.param || 0 : 0;
		if( this.m_param.className && this.m_param.className == 'ext.algorithm.queue' ) this.m_paramType = 'CQueue';
	}

	swat.ext.CTimer.prototype =
	{
		/**
		 * 启动计时器
		 *
		 * @param __maxRunCount: (可选)最大运行次数
		 * @return 当前对象
		 */
		start: function( __maxRunCount )
		{
			if( typeof this.m_timerProc != 'function' ) return false;
			if( __maxRunCount ) this.m_maxRunCount = __maxRunCount;
			this.m_runCon = 0;
			this._run();
			return this;
		},

		/**
		 * 状态复位
		 */
		reset: function()
		{
			this.m_runCon = 0;
			this.m_runCount = 0;
			return this;
		},

		/**
		 * 主运行方法, 不允许直接调用
		 */
		_run: function()
		{
			// 是否设为永久运行, 或是否已超过运行次数
			if( this.m_runCount >= this.m_maxRunCount && this.m_maxRunCount != -1 )
			{
				// 是则清除定时器
				if( this.m_hTimer ) window.clearTimeout( this.m_hTimer );
				return true;
			}

			// 是否达到最大并发上限
			var r = 1;
			if( this.m_maxCon > 0 && this.m_runCon < this.m_maxCon )
			{
				// 加并发锁
				this._lock();

				// 未达到则根据参数类型调用回调函数
				if( this.m_paramType == 'CQueue' )
				{
					r = this.m_timerProc( this.m_param.pickNext(), this );
				}
				else
				{
					r = this.m_timerProc( this.m_param, this );
				}

				// 加运行次数计数
				this.m_runCount++;
			}

			// 若回调函数返回 false 则中止定时器, 否则继续设置下一个定时器
			if( r != false )
			{
				var _I = this;
				this.m_hTimer = window.setTimeout( function(){ _I._run()}, this.m_interval );
			}

			return true;
		},

		/**
		 * 取当前运行次数
		 *
		 * @return 当前已运行任务次数
		 */
		getRunCount: function()
		{
			return this.m_runCount;
		},
		
		/**
		 * 设置计时器运行时间间隔
		 *
		 * @param A: 时间(毫秒)
		 * @return 当前对象
		 */
		setInterval: function( A )
		{
			this.m_interval = A;
			return this;
		},

		/**
		 * 并发加锁(不应直接调用)
		 *
		 * @return 当前对象
		 */
		_lock: function()
		{
			// 简单将并发计数加1
			this.m_runCon++;
			return this;
		},

		/**
		 * 并发解锁
		 *
		 * 回调函数返回前必须调用此函数进行解锁
		 * @return 当前对象
		 */
		unlock: function()
		{
			// 并发计数减1
			this.m_runCon = Math.max( 0, this.m_runCon - 1 );
			return this;
		},

		/**
		 * 取当前并发任务数
		 *
		 * @return 当前正在执行的并发任务数
		 */
		getConcurrence: function()
		{
			return this.m_runCon;
		}
	}
}
